package day20180128.testProxyDynamic;




import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by 14394 on 2018/1/28.
 */
public class TimerInvocationHandler implements InvocationHandler {

    //目标对象，通过反射机制获得
    private Object target;

    //构造方法
    public TimerInvocationHandler(Object target) {
        this.target = target;
    }

    /*参数：
     *      proxy:代理对象的引用，proxy变量中保存代理对象的内存地址（这个参数很少用）
     *      method:目标对象的目标方法
     *      args:目标对象的目标方法执行的时候所需要的实参
      */
    //对一类计算时间的抽象，动态代理
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //开始时间
        long begin = System.currentTimeMillis();

        //执行目标对象中的方法
        Object retValue = method.invoke(target,args);

        //结束时间
        long end = System.currentTimeMillis();

        //计算时间
        System.out.println("耗费时间："+ (end-begin)+ "毫秒");

        return retValue;
    }

    /*
    *   注意:  JDK内置的动态代理Proxy只能代理接口
    *   （如果既想代理接口又想代理抽象类需要使用第三方组件：例如 cglib）*/
    //测试动态代理
    public static void main(String[] args) {
        //创建目标对象
        ILogin target = new ILoginImpl();

        /*参数
        ClassLoader loader; 代理类的类装载器 这里的类装载器主要用来装载再内存中生成的哪个临时字节码，代理类的类装载器需要和目标类的类装载器一样

        Class[] interfaces;代理类实现的接口 代理类和目标类必须实现”同一些“接口（一个类可以同时实现多个接口）

        InvocationHandler handler;代理类的代理方法 当代理对象调用代理方法的时候，”注册“在调用处理器中的invoke方法会自动调用
       */

        //创建代理对象：通过JDK内置的动态代理类  java.lang.reflect.Proxy完成代理对象的动态创建
        ILogin proxy = (ILogin) Proxy.newProxyInstance(target.getClass().getClassLoader(),new Class[]{ILogin.class},new TimerInvocationHandler(target));

        //通过执行代理对象的代理方法去执行目标对象的目标方法

        proxy.login();

        proxy.logout();
    }
}
